package main.java.message;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.List;

import main.java.regression.Regression;
import main.java.regression.User;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

public class IncomingMessageHandler implements Runnable {
	private Socket socket;
	private String senderIP;
	private Regression regression;

	public IncomingMessageHandler(Socket socket, Regression regression) {
		this.socket = socket;
		this.regression = regression;
		setSenderIP(socket.getRemoteSocketAddress().toString());
	}

	public String getSenderIP() {
		return senderIP;
	}

	public void setSenderIP(String senderIP) {
		this.senderIP = senderIP;
	}

	@Override
	public void run() {
		try {
			String msg = "";
			BufferedReader input = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
			String line;
			while ((line = input.readLine()) != null) {
				msg = msg + line + "\n";
			}
			socket.close();
			processMsg(msg);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void processMsg(String msg) {
		try {
			System.out.println(msg);
			JSONParser parser = new JSONParser();
			JSONObject obj = (JSONObject) parser.parse(msg);
			String type = (String) obj.get(MessageTags.TYPE.getTag());
			String requireAck = (String) obj.get(MessageTags.ACK_REQUIRED
					.getTag());
			if (requireAck != null
					&& requireAck.equals(MessageContents.TRUE.toString())) {
				ackMessage(obj);
			}
			if (type.equals(MessageContents.ACKNOWLEDGEMENT.getContent())) {
				handleMsgAck(obj);
			} else if (type.equals(MessageContents.PING.getContent())) {
				handleMsgPing();
			}
			System.out.println("==================" + type);
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	public void handleMsgAck(JSONObject obj) {
		regression.removeUnAckedMessage((String) obj
				.get(MessageTags.RECIEVED_MESSAGE_ID.getTag()));
	}

	public void handleMsgPing() {
		User sender = getSender();
		sender.setConnected(true);
		System.out.println("User " + sender.getIp() + " is connected");
	}

	public void ackMessage(JSONObject obj) {
		User sender = getSender();
		if (sender == null)
			return;
		Message msg = new Message(MessageContents.ACKNOWLEDGEMENT);
		msg.put(MessageTags.RECIEVED_MESSAGE_ID,
				(String) obj.get(MessageTags.ID.getTag()));
		(new MessageSender(sender)).sendMessage(msg.toString());
	}

	public User getSender() {
		List<User> list = regression.getDataSourceUsers();
		for (User u : list) {
			if (senderIP.contains(u.getIp()))
				return u;
		}
		return null;
	}

}
